import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { SystemUserDecoratorType } from 'src/decorator/operuser.decorator';
import { OperType } from 'src/global-type';
import FileLogger from 'src/utils/file-logger';
import { CreateSystemLogType } from './system-log.interface';
import { SystemLogDocument } from './system-log.schema';
import {
  buildSysRecordData,
  getOperInfo,
  TargetInfoType,
  TargetType,
} from './utils';

@Injectable()
export class SystemLogService {
  private readonly logger = new FileLogger(SystemLogService.name);
  constructor(
    @InjectModel('SystemLog')
    private systemLogModel: Model<SystemLogDocument>,
  ) {}

  async querySystemLogList(params, sort) {
    try {
      const { current, pageSize, ...statement } = params;
      if (statement.userName)
        statement.userName = new RegExp(statement.userName);
      const total = await this.systemLogModel.countDocuments(statement);
      const data = await this.systemLogModel
        .find(statement)
        .sort(sort)
        .skip(current * pageSize)
        .select({ oldData: 0, newData: 0 })
        .limit(pageSize);
      return { total, data };
    } catch (err) {
      this.logger.printError(this.querySystemLogList.name, err);
      return { total: 0, data: [] };
    }
  }

  async deleteOneSystemLog(params: { _id: string }) {
    try {
      const res = await this.systemLogModel.deleteOne(params);
      if (res.deletedCount) return true;
      return false;
    } catch (err) {
      this.logger.printError(this.deleteOneSystemLog.name, err);
      return false;
    }
  }

  async findOneSystemLog(params: { _id: string }, projection: any = null) {
    try {
      return await this.systemLogModel.findOne(params, projection);
    } catch (err) {
      this.logger.printError(this.findOneSystemLog.name, err);
      return null;
    }
  }

  // 判断上次查询操作是否在一分钟之内
  async getLastLog(userId: string, targetType: TargetType) {
    try {
      const datas = await this.systemLogModel
        .find({ userId, operType: OperType.QUERY })
        .sort({ operTime: -1 })
        .limit(1);
      if (!datas || datas.length < 1) return true; // 无上次查询记录时，记录当前
      if (datas[0].targetType !== targetType) return true; // 两次查询非相同模块时，均记录
      const last = datas[0].operTime.valueOf();
      const now = Date.now();
      const res = (now - last) / 1000;
      return res > 120;
    } catch (err) {
      this.logger.printError(this.getLastLog.name, err);
      return true;
    }
  }

  async insertSysLog(
    opUser: SystemUserDecoratorType,
    opType: OperType,
    targetInfo: TargetInfoType,
    appendix?: string,
  ) {
    try {
      if (opType === OperType.QUERY) {
        // 查询操作2分钟记录一次日志
        const isInsert = await this.getLastLog(
          opUser?.id,
          targetInfo.targetType,
        );
        if (!isInsert) return null;
      }

      const newLog = buildSysRecordData(
        getOperInfo(opUser),
        opType,
        targetInfo,
        appendix,
      );

      return await this.systemLogModel.create(newLog);
    } catch (err) {
      this.logger.printError(this.insertSysLog.name, err);
      return null;
    }
  }
  async createSysLog(data2create: CreateSystemLogType) {
    try {
      return await this.systemLogModel.create(data2create);
    } catch (err) {
      this.logger.printError(this.createSysLog.name, err);
      return null;
    }
  }
}
